package movement

import (
	pos "code.google.com/p/gochess/position"
	"fmt"
	"strings"
)

const MaxMoveSortValue = int32((1<<31 - 1) >> pos.BitSizeMove)

// Movelist is a list of weighted moves.
type Movelist struct {
	moves        [256]pos.Move
	max, current int32
}

// Len returns the number of list elements.
func (list *Movelist) Len() int32 {
	return list.max
}

// Clear cleares the list.
func (list *Movelist) Clear() {
	list.max, list.current = 0, 0
}

// Rewind sets the internal pointer to the first element,
func (list *Movelist) Rewind() {
	list.current = 0
}

// Appends adds the move at the end of the list.
func (list *Movelist) Append(move pos.Move, weight int32) {
	list.moves[list.max] = move | pos.Move(weight<<pos.BitSizeMove)
	list.max++
}

// todo: write tests for list
//
// SetWeight sets the weight of the move which was obtained by the last Next method.
func (list *Movelist) SetWeight(weight int32) {
	list.moves[list.current-1] = list.moves[list.current-1]&pos.BitMaskMove | pos.Move(weight<<pos.BitSizeMove)
}

// Next returns the next move in the list.
// If there are no moves left NoMove will be returned.
func (list *Movelist) Next() pos.Move {
	if list.current == list.max {
		return pos.NoMove
	}
	list.current++
	return list.moves[list.current-1] & pos.BitMaskMove
}

// Sort sorts the list using insertion sort.
func (list *Movelist) Sort() {
	//	stats.MoveListSizeForSort[list.Len()]++
	for i := int32(1); i < list.max; i++ {
		pivot := list.moves[i]
		j := i
		for ; j > 0 && pivot>>pos.BitSizeMove > list.moves[j-1]>>pos.BitSizeMove; j-- {
			list.moves[j] = list.moves[j-1]
		}
		list.moves[j] = pivot
	}
}

func (list *Movelist) String() string {
	s := make([]string, list.max)
	for i := int32(0); i < list.max; i++ {
		s[i] = fmt.Sprintf("%v:{%v %v}", i,
			list.moves[i]&pos.BitMaskMove, int32(list.moves[i]>>pos.BitSizeMove))
	}
	return "[" + strings.Join(s, " ") + "]"
}
